// 13.1 拷贝、赋值与销毁
/**
 * 我们将以最基本的操作——拷贝构造函数、拷贝赋值运算符和析构函数作为开始。我们在13.6节（第470页）中将介绍移动操作（新标准所引入的操作）。
 */

#include <iterator>
#include <vector>
#include <list>
#include <deque>
#include <forward_list>
#include <string>
#include <array>
#include <stack>
#include <queue>
#include <algorithm>
#include <numeric>
using std::swap;
using std::vector, std::list, std::deque, std::forward_list, std::string, std::array, std::stack, std::queue;
#include "../Chapter07/Sales_data.h"
#include <iostream>
using std::begin, std::cbegin, std::end, std::cend, std::find, std::accumulate, std::equal, std::fill, std::fill_n, std::back_inserter;
using std::cin, std::cout, std::endl;
using std::copy, std::replace, std::replace_copy;
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <memory>
#include <new>
using namespace std;

// 演示析构函数
class Foo
{
public:
    ~Foo();                      // 析构函数
    Foo &operator=(const Foo &); // 赋值运算符
    Foo();                       // 默认构造函数
    Foo(const Foo &);            // 拷贝构造函数
};

// 演示等价于合成析构函数的析构函数
class Foo1{
public:
    ~Foo1() {} // 成员被自动销毁，除此之外不需要做其他事情
};

int main()
{
    // 13.1.3 析构函数
    // 析构函数执行与构造函数相反的操作：构造函数初始化对象的非static数据成员，还可能做一些其他工作；
    // 析构函数释放对象使用的资源，并销毁对象的非static数据成员。
    // 析构函数是类的一个成员函数，名字由波浪号接类名构成。它没有返回值，也不接受参数：[插图]
    {
        Foo foo1;
    } // 程序块结束，Foo执行其析构函数

    // 析构函数完成什么工作
    // 在一个构造函数中，成员的初始化是在函数体执行之前完成的，且按照它们在类中出现的顺序进行初始化。
    // 在一个析构函数中，首先执行函数体，然后销毁成员。成员按初始化顺序的逆序销毁。
    // 通常，析构函数释放对象在生存期分配的所有资源。
    // 在一个析构函数中，不存在类似构造函数中初始化列表的东西来控制成员如何销毁，析构部分是隐式的。
    // 成员销毁时发生什么完全依赖于成员的类型。销毁类类型的成员需要执行成员自己的析构函数。内置类型没有析构函数，因此销毁内置类型成员什么也不需要做。
    // 与普通指针不同，智能指针（参见12.1.1节，第402页）是类类型，所以具有析构函数。因此，与普通指针不同，智能指针成员在析构阶段会被自动销毁。

    // 什么时候会调用析构函数
    // 无论何时一个对象被销毁，就会自动调用其析构函数：
    // 1. · 变量在离开其作用域时被销毁。
    // 2. · 当一个对象被销毁时，其成员被销毁。
    // 3. · 容器（无论是标准库容器还是数组）被销毁时，其元素被销毁。
    // 4. · 对于动态分配的对象，当对指向它的指针应用delete运算符时被销毁（参见12.1.2节，第409页）。
    // 5. · 对于临时对象，当创建它的完整表达式结束时被销毁。
    // 当指向一个对象的引用或指针离开作用域时，析构函数不会执行。
    
    // 合成析构函数
    // 当一个类未定义自己的析构函数时，编译器会为它定义一个合成析构函数（synthesized destructor）。
    // 例如，下面的代码片段等价于Sales_data的合成析构函数：[插图]
    {
        Foo1 foo;
    } // 程序块结束，Foo1执行其析构函数
    // 在（空）析构函数体执行完毕后，成员会被自动销毁。
    // 析构函数体自身并不直接销毁成员，在整个对象销毁过程中，析构函数体是作为成员销毁步骤之外的另一部分而进行的。
    // 认识到析构函数体自身并不直接销毁成员是非常重要的。成员是在析构函数体之后隐含的析构阶段中被销毁的。




    return 0;
}